# -*- coding: utf-8 -*-
## ************************************************************* INTERFBEHAVIOR.PY
## * Description:
## * This code is responsable for treat application buttons Behaviors.
## * (events, routines and classes) that exist in the glwidget canvas.
## *******************************************************************************
## * Created in: 2007-01-07
## * Last updated in: 2008-05-06
## *******************************************************************************
## * Authoring: Elisabete Thomaselli Nogueira and Victor S. Bursztyn
## * Orientation: Claudio Esperanca
## *******************************************************************************
from interfPrototipo import *       ## Main interface Layout to Prototype
from interfTextDoc import *         ## Interface Layout to Documentation Window
from animations import *            ## Animation needs
import sound                        ## Pygame wave sound player

from PyQt4 import *
from PyQt4.QtCore import *
## QtGui.QIcon used in interfPrototipo.py refers to some images .png reside in /icones/, by creating a .qrc file that
## lists it. After that, a Python module has to be created with command pyrcc4 on ## the .qrc file.
import r_icones_rc                  ## Python module with interface image buttons.
import os                           ## Verify current operation system

def velocity(vel):
    """## Return a factor to calculate the quantity of keyframes.
    @param vel: Controls the frame rate by interface parameter velocity (Slow, Medium or High)"""
    if vel == "Slow":
       mult = 1
    elif vel == "Medium":
       mult = 2
    elif vel == "High":
       mult = 3

    return mult
    
class myTextDocDialog(Ui_Dialog_Doc):
## Restore interfTextDoc modal window parameters.
## If prototype object has text documentation stored, this text is retrieved.

    def changeCurrentColor(self):

	    white = QtGui.QColor(255,255,255)
	    newColor = QtGui.QColorDialog.getColor(white, self)
	    
	    if newColor.isValid():
	        self.setTextColor(newColor)

    def accept(self):
        """
        OnDialogSubmition
        """    
        print os.name
        return self.textDocEdit.document()   ## Return text documentation written.

    def initDoc(self, doc):
        """
        OnDialogInitialization
        """
        if (doc != None):
            self.textDocEdit.setDocument(doc)  ## Retrieve text documentation stored previously.


class myAnimParameterDialog(Ui_Dialog_Anim):    
## Restore interfAnim modal window parameters.

    def accept(self):
        """
        OnDialogSubmition
        """
        return self.comboBox_Anim.currentText(), self.comboBox_Stop.currentText(), self.spinBox_Ini.value(), self.spinBox_Last.value(), self.comboBox_Vel.currentText()


class myMainBehavior(QtGui.QMainWindow, Ui_MainWindow):
## Mainly behavior class.

    def __init__(self, parent=None):
        ## Constructor.
        QtGui.QMainWindow.__init__(self)
        self.setupUi(self)

        #  Describe system majors

        ## **************************************************************************************
        ## * Describes actions to signals emited in prototype functions.
        ## **************************************************************************************
        self.connect(self.widget, QtCore.SIGNAL("modelLoaded"), self.updateTree_addModel) ## Include new model in hierarchy.
        self.connect(self.widget, QtCore.SIGNAL("animationLoaded"), self.updateTree_addAnim) ## Include new model in hierarchy.
        self.connect(self.widget, QtCore.SIGNAL("modelDeleted"), self.updateTree_delModel) ## Delete model from hierarchy.
        self.connect(self.widget, QtCore.SIGNAL("presentationLoaded"), self.updateTree_addModel) ## Include saved  presentation in the current project.
        self.connect(self.widget, QtCore.SIGNAL("sceneCleared"), self.updateTree_clearScene) #Clear hierarchy structure scene
        self.connect(self.treeWidget, QtCore.SIGNAL("currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)"), self.updateScene) #Update scene according to hierarchy information.
        self.connect(self.widget, QtCore.SIGNAL("objectSelected"), self.updateTree_changeSelection)

        ## **************************************************************************************
        ## * Describes action buttons from frame interfPrototipo.ui and their connects and signals
        ## **************************************************************************************
        self.connect(self.action_New, QtCore.SIGNAL("triggered()"), self.widget.newProject)
        ## Open model from macchine directory
        self.connect(self.action_Open, QtCore.SIGNAL("triggered()"), self.widget.openPresentation)
        ## Apos rodar pyuic4, alterar para actionOpen_Model
        self.connect(self.action3D_Model, QtCore.SIGNAL("triggered()"), self.widget.openModel)
        self.connect(self.action_Import, QtCore.SIGNAL("triggered()"), self.widget.importSlide)
        #self.connect(self.action_Export
        self.connect(self.action_Save, QtCore.SIGNAL("triggered()"), self.widget.savePresentation)
        self.connect(self.actionSave_As, QtCore.SIGNAL("triggered()"), self.widget.save_As_Presentation)
        self.connect(self.action_Quit, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("quit()")) ## Exit 3DbyStep application
        #self.connect(self.actionStructure_Content
        #self.connect(self.actionScene
        ## -- Actions related to toolBar
        self.connect(self.actionBasic_File_Functions, QtCore.SIGNAL("triggered()"), self.createB_Main)
        self.connect(self.actionDocumentation, QtCore.SIGNAL("triggered()"), self.createB_Doc)
        self.connect(self.actionAnimation, QtCore.SIGNAL("triggered()"), self.createB_Anim)
        self.connect(self.actionDraw, QtCore.SIGNAL("triggered()"), self.createB_Draw)
        self.connect(self.actionPresentation_Content, QtCore.SIGNAL("triggered()"), self.createB_Cont)

        self.connect(self.action3DbyStep_Documentation, QtCore.SIGNAL("triggered()"), QtGui.qApp, QtCore.SLOT("aboutQt()"))
        #self.connect(self.actionAbout
        #self.connect(self.actionReload
        #self.connect(self.actionTransicao_Quadro
        self.connect(self.actionZoom_Out, QtCore.SIGNAL("triggered()"), self.widget.zoomOut)
        self.connect(self.actionZoom_In, QtCore.SIGNAL("triggered()"), self.widget.zoomIn)
        #self.connect(self.action_Rotate
        #self.connect(self.action_Translate
        #self.connect(self.actionView_Detail, QtCore.SIGNAL("triggered()"), self.
        #self.connect(self.action_Transform
        ## self.connect(self.action_Group, QtCore.SIGNAL("triggered()"),
        #self.connect(self.action_Ungroup
        #self.connect(self.action_Explode
        ## Change existing model color
        self.connect(self.actionModel_Color, QtCore.SIGNAL("triggered()"), self.widget.changeColor)
        ##Action actionDoc_Include was used to input text documentation to determined object. Starts commentary form presentation
        self.connect(self.actionDoc_Include, QtCore.SIGNAL("triggered()"), self.displayTextDoc)
        #self.connect(self.actionDoc_Edit, QtCore.SIGNAL("triggered()"), self.slotFont)
        #self.connect(self.actionDoc_Exclude, QtCore.SIGNAL("triggered()"),
        #self.connect(self.actionDoc_Hide, QtCore.SIGNAL("triggered()"),
        self.connect(self.actionDoc_bySound, QtCore.SIGNAL("triggered()"), self.sound)
        ##Action actionDoc_Metadata was used to input text documentation to current slide. Starts commentary form presentation
        self.connect(self.actionDoc_Metadata, QtCore.SIGNAL("triggered()"), self.displayTextDoc)
        self.connect(self.action_Presentation,QtCore.SIGNAL("triggered()"), self.widget.openPresentation)
        ## Open model from macchine directory, Similarly to command connect(self.action_Open
        self.connect(self.action_3DModel, QtCore.SIGNAL("triggered()"), self.widget.openModel) #("circle.obj"))
        #self.connect(self.action_Picture
        self.connect(self.action_Scale, QtCore.SIGNAL("triggered()"), self.widget.scaleFactor)
        self.connect(self.action_Arrow, QtCore.SIGNAL("triggered()"), self.widget.newArrowModel)
        self.connect(self.action_Cube, QtCore.SIGNAL("triggered()"), self.widget.newCubeModel)
        self.connect(self.action_Sphere, QtCore.SIGNAL("triggered()"), self.widget.newSphereModel)
        self.connect(self.action_Cylinder, QtCore.SIGNAL("triggered()"), self.widget.newCylinderModel)
        #self.connect(self.action_Plano, QtCore.SIGNAL("triggered()"), self.widget.newPlaneModel)
        self.connect(self.action_Gear, QtCore.SIGNAL("triggered()"), self.widget.newGearModel)
        self.connect(self.action_Star, QtCore.SIGNAL("triggered()"), self.widget.newStarModel)
        ## **************************************************************************************
        ## * Describes action buttons from frame interfAnim.ui and their connects and signals
        ## **************************************************************************************
        self.connect(self.widget, QtCore.SIGNAL("modelMoved(int)"), self.updateSlider) #Include new model in hierarchy
        self.connect(self.action_Play, QtCore.SIGNAL("triggered()"), self.startAnimation)
        self.connect(self.action_AnimAppear, QtCore.SIGNAL("triggered()"), self.controlAnimation)    ## Define object to appear in scene and previous time sleep.
        self.connect(self.action_AnimDesappear, QtCore.SIGNAL("triggered()"), self.widget.plotGraph)    ## Define object to appear in scene and previous time sleep.
        self.connect(self.horizontalSlider, SIGNAL("valueChanged(int)"), self.move2Scene)
        self.connect(self.pauseButton, SIGNAL("clicked()"), self.pauseOrResume)
        self.connect(self.quitButton, SIGNAL("clicked()"), self.playQuit)
        self.connect(self, QtCore.SIGNAL("pauseResume(bool)"), self.widget.playHandler)
        self.connect(self.widget, QtCore.SIGNAL("quitPlayer(int)"), self.playQuit)


        ## Ticks count for the time-line
        self.animationTimer = QTimer()
        self.animationTimer.setSingleShot(False)
        ## snimationTimer will time out every 1000/fps milliseconds.
        self.connect(self.animationTimer, SIGNAL("timeout()"), self.widget.updateScene)
        self.horizontalSlider.setRange(1, 200)
        self.horizontalSlider.setValue(1)
        self.Running = False
        self.animType = None

        ## Inicia com as toolBars desativadas
        self.toolBar_B_Anim = True
        self.toolBar_B_Cont = True
        self.toolBar_B_Doc = True
        self.toolBar_B_Draw = True
        self.toolBar_B_Main = True


    #***********************************************************************************************
    
    ## Define different procedures to "stop and go back" and "stop here"
    def playQuit(self):     ## Quando forem varios objetos animados no mesmo periodo, o termino serￃﾡ um comportamento individual
        self.playerExit = self.stopScript(self.Stop)

        if self.playerExit == 1:
            self.widget.playStop(1)
        else:
             self.widget.playStop(2)
        self.animationTimer.stop()  ## Here we stop a timer which will time out every 1000/fps milliseconds.


    def updateSlider(self, args):
        """Updates slider position to reproduce current position in timeline.
        @param frameCount: groups related to this object."""
        self.frameCount = args
        print "atualizar posicao corrente no controle de slider", self.frameCount
        self.horizontalSlider.setValue(self.frameCount)
        self.widget.repaint()

    def acceptStop(self):       ## Tratar fim da animacao.
        self.emit(QtCore.SIGNAL("quitPlayer(int)"), self.playerExit)
        ## Se animacao toca e volta para o frame inicial, devolver valores passados para o startAnimation

    def pauseOrResume(self):
        self.Running = not self.Running
        self.pauseButton.setText("Pa&use" if self.Running else "Res&ume")
        self.emit(QtCore.SIGNAL("pauseResume(bool)"), self.Running)

    def changeValue(self, event):
        self.cw = self.slider.value()
        self.wid.repaint()

    def move2Scene(self):
        print "*** ",  self.horizontalSlider.value()
        self.curFrame = self.horizontalSlider.value()
        print "frame ",  self.curFrame
        self.widget.update2Scene(self.curFrame)

    def controlAnimation(self):
        """Open window with previously defined animation.
        @param Anim: animation routine text to be performed
        @param animType: animation routine to be performed
        @param Stop: procedure text to be performed when fisnishing an' animation
        @param playerExit: procedure to be performed when fisnishing an' animation
        @param initFrame: the first frame to be interpolated.
        @param lastFrame: the last frames to be displayed.
        @param Vel: velocity text associate to display (3 modes)
        @param vel: velocity associate to display (3 modes)

        @param index_m: selected object id number"""

        ## Defines parameters to animation
        self.Anim, self.Stop,  self.initFrame, self.lastFrame, self.Vel = self.displayAnimParam()

        self.vel = velocity(self.Vel)
        self.animType = self.animScript(self.Anim)
        self.playerExit = self.stopScript(self.Stop)
        self.horizontalSlider.setValue(1)       ## Always start player in frame one.

    """
    def verifyAnimation(self):
        ## Test if exists some animation
        try:
            self.Anim
        except AttributeError:
        # x doesn't exist, do something
            QtGui.QMessageBox.about(self, self.tr("Player Application"),
                self.tr("There aren't pre-defined animations inside this slide. Create an'animation before using <b>player animations</b> control."))

        else:
        # x exists, do something else
             self.startAnimation()
    """

    def startAnimation(self):
        #def verifyAnimation(self):
        print "self.animType ", self.animType
        if self.animType != "None":

            ## Animation timeline
            self.frameCount = 1       ## Always start player with frameCount = 1.
            self.curFrame = 1         ## Always start player with curFrame = 1.
            self.lastFrame = 200      ## Always play from the first frame (1) until the last frame (200)

            self.connect(self.animationTimer, SIGNAL("timeout()"), self.widget.updateScene)
            fps = 20
            #mult = 1 #fator de aceleracao
            #print  "startAnimation ",self.Anim, self.Stop,  self.initFrame, self.lastFrame, self.Vel,  self.delayTime

            self.animationTimer.start(1000/fps)  ## Here we create a timer which will time out every 1000/fps milliseconds.
            #self.Running = True

            self.frameCount = self.initFrame
            self.Running = True
            #myScene = glWidget(None, 20 * mult, self.initFrame, self.lastFrame, self.Running)
            # self.interpTrans =
            self.widget.animateObj(self.animType, self.playerExit, self.initFrame,  self.lastFrame, self.vel, self.Running)

    def displayAnimParam(self):
        ## Inicialize the input dialog for text documentation.
        current = self.treeWidget.currentItem()

        self.parameterDialog = QtGui.QDialog(self)
        self.parameterDialog.setModal(True)
        animDocInterf = myAnimParameterDialog()
        animDocInterf.setupUi(self.parameterDialog)
        if (self.parameterDialog.exec_() == QtGui.QDialog.Accepted):
            self.Anim, self.Stop, self.initFrame, self.lastFrame, self.Vel = animDocInterf.accept()

            ## Por esse texto na arvore hierarquica, junto com o icone
            #(self.animType,",init=",self.initFrame,",last=", self.lastFrame)           anim
            animListItem = [self.animType,self.initFrame, self.lastFrame]
            print "displayAnimParam ", animListItem
            self.widget.textAnimation(animListItem)

            ##VER current.setIcon(0, QtGui.QIcon(":/new/prefix1/icones/icones/apresentar_comentario.JPG"))
            #current.setIcon(0, QtGui.QIcon(":/new/prefix1/icones/icones/efeito_aparecer.png"))

            return self.Anim, self.Stop,  self.initFrame, self.lastFrame, self.Vel


    def animScript(self, animText):
        """## Return a script name.
        @param anim: Controls animation script that will be execute"""
        print "animText ", animText
        if animText == "Translate and rotate":
           animType = "TransRot"
        elif animText == "Bring to front":
           animType = "bringObj"
        elif animText == "Go to the top right corner":
           animType = "topRight"
        elif animText == "Go to the bottom right corner":
           animType = "botRight"
        elif animText == "Go to the top left corner":
           animType = "topLeft"
        elif animText == "Go to the bottom left corner":
           animType = "botLeft"

        return animType


    def stopScript(self, stopText):
        """## Return a script name.
        @param playerExit: Controls animation exit procedure"""      
        print "animText ", stopText
        if stopText == "and return to the first frame":   ## = 1 -- Retorna ao frame inicial
           playerExit = 1
        elif stopText == "and stay":  ## = 2 -- Fica no frame corrente
           playerExit = 2

        return playerExit
        
    #***********************************************************************************************
    # Update Tree Presentation functions.
    #***********************************************************************************************
    
    ## Clear slide scene and tree window either.
    def updateTree_clearScene(self):
        QtGui.QTreeWidget.clear(self.treeWidget)  #self.treeWidget)

    def updateTree_addModel(self, *args):
        """Updates tree structure to reproduce informations relative to loaded elements #and defined animations.
        @param groups: groups related to this object.
        @param name: the name of the object to be inserted."""
        groups = args[0][0]
        name = str(args[0][1])
        modelitem = QtGui.QTreeWidgetItem(self.treeWidget) ## Update project hierarchy inputing current model.
        modelitem.setText(0,QtGui.QApplication.translate("MainWindow", name, None, QtGui.QApplication.UnicodeUTF8))

        for group in range(1,len(groups)-1):
            ## Update project hierarchy including pieces of the current model, except for the first and last groups.
            ## These occurs, once the first and last groups importance are internal only.
            groupitem = QtGui.QTreeWidgetItem(modelitem)
            groupitem.setText(0,QtGui.QApplication.translate("MainWindow", str(groups[group].groupName), None, QtGui.QApplication.UnicodeUTF8))

    def updateTree_addAnim(self, *args):
        """Updates tree structure to reproduce informations relative to the defined animations.
        #@param groups: groups related to this object.
        @param name: the name of the object to be inserted."""
        groups = args[0][0]
        name = str(args[0][1])
        current = self.treeWidget.currentItem()

        #modelitem = QtGui.QTreeWidgetItem(current) ## Update project hierarchy inputing current model.
        animationitem = QtGui.QTreeWidgetItem(current)
        animationitem.setText(0,QtGui.QApplication.translate("MainWindow", name, None, QtGui.QApplication.UnicodeUTF8))

    def updateTree_delModel(self):
        #def updateTree_delModel(self, *args):
        ##m3 def updateTree_delModel(self, model, groups):
        """Deletes a defined model from tree structure.
        @param model: index of the selected object to be deleted.
        @param groups: index of specific groups to be deleted in the model."""
        #model = args[0][0]
        #groups = args[0][1]

        items = QtGui.QTreeWidgetItem(self.treeWidget)
        selected = self.treeWidget.selectedItems()

        print "selected ",selected

        for item in selected:
            self.treeWidget.removeItemWidget(item, 0)  ##  RemoveItemWidget only exists after PyQt 4.3.3
            # This is faster than using the Tree's removeItemWidget, which is really slow.
            ##parent = item.parent()
            ##parent.removeChild(item)

        #self.delete()

    def delete(self):
        #i=self.treeWidget.currentItem()
        i=self.treeWidget.selectedItems()
        if not i:
            return
        p=i.parent()
        if p:
            p.takeChild(p.indexOfChild(i))

    ##
    def updateTree_changeSelection(self, *args):
        print "The selected object in glwidget will be selected in the tree either."
        selectionName = str(args[0][0])
        selectedItem = self.treeWidget.findItems(selectionName, QtCore.Qt.MatchExactly, 1)
        # print selectedItem
        for item in selectedItem:
            # print str(item.text(0))
            self.treeWidget.setItemSelected(item, True)

    #***********************************************************************************************
    
    def updateScene(self):
        current = self.treeWidget.currentItem()
        #Whenever some item is selected in hierarchy window,
        #the corresponding group is shown in the glWidget, sending base (pai) and item names.
        if (current.parent() != None):
            self.widget.selectGroup(current.parent().text(0), current.text(0))
        else:
            self.widget.selectGroup("", current.text(0))



    ## Treat Text Dialog Modal Window
    def displayTextDoc(self):

        # Este bloco ainda diz respeito à forma antiga de documentação
        """
        current = self.treeWidget.currentItem()

        if (current != None):       #Inicialize the input dialog for text documentation.
            self.textDocDialog = QtGui.QDialog(self)
            self.textDocDialog.setModal(True)
            textDocInterf = myTextDocDialog()
            textDocInterf.setupUi(self.textDocDialog)

            #prevDoc = self.widget.getCurrentDoc()
            #print "prevDoc ",prevDoc
            #if (prevDoc != None): #Check if there is some associated documentation
            #	textDocInterf.initDoc(prevDoc)
            if(self.textDocDialog.exec_() == QtGui.QDialog.Accepted):
                tempDoc = textDocInterf.accept()
                #print "tempDoc ", tempDoc
                self.widget.textDoc(tempDoc)
                #current.setIcon(0, QtGui.QIcon(":/new/prefix1/icones/icones/apresentar_comentario.JPG"))
        else:
            print "Document associated to slide"
            ## Text written describes metadata information
        """

        self.textDocDialog = QtGui.QDialog(self)
        self.textDocDialog.setModal(True)
        textDocInterf = myTextDocDialog()
        textDocInterf.setupUi(self.textDocDialog)
        self.connect(textDocInterf.pushButton, SIGNAL("clicked()"), textDocInterf.changeCurrentColor)
        if(self.textDocDialog.exec_() == QtGui.QDialog.Accepted):
            tempDoc = textDocInterf.accept()
            self.widget.textDoc(tempDoc)

    def sound (self):
        sound.sound_music()

    def createB_Main(self):
        print "B_Main"
        self.toolBar_B_Main = not self.toolBar_B_Main
        if not self.toolBar_B_Main:
            self.createBar_Main(self)

    def createB_Doc(self):
        print "B_Doc"
        self.toolBar_B_Doc = not self.toolBar_B_Doc
        if not self.toolBar_B_Doc:
            self.createBar_Documentation(self)

    def createB_Anim(self):
        print "B_Anim"
        self.toolBar_B_Anim = not self.toolBar_B_Anim
        if not self.toolBar_B_Anim:
            self.createBar_Animation(self)

    def createB_Draw(self):
        print "B_Draw"
        self.toolBar_B_Draw = not self.toolBar_B_Draw
        if not self.toolBar_B_Draw:
            self.createBar_Draw(self)

    def createB_Cont(self):
        print "B_Cont"
        self.toolBar_B_Cont = not self.toolBar_B_Cont
        if not self.toolBar_B_Cont:
            self.createBar_Content(self)

    #******************************************************************************************
    # Help and About 
    #******************************************************************************************
   
    def on_actionAbout_triggered (self):
           #def actionAbout(object):
           QtGui.QMessageBox.about(self, self.tr("About Application"),
                   self.tr("The <b>Application</b> prototype demonstrates how to "
                           "write modern authorize GUI applications using PyQt, OpenGL, with a menu bar, "
                           "toolbars, and a status bar."))

    def on_action3DbyStep_Documentation_triggered (self):
        print "document"
